using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Windows.Forms;


namespace THSLib
{
    /// <summary>
    /// THSDataSet Class
    /// </summary>
    public class THSDataSet : DataSet
    {
        /// <summary>
        /// Constructor THSDataSet
        /// </summary>
        /// <param name="iTHSDataSetID">THSDataSet ID</param>       

        public THSDataSet(int iTHSDataSetID)
        {
            BeginInit();
            InitDataSet(iTHSDataSetID);
            EndInit();
        }

        public THSDataSet(int iFieldID, String strDataSetName)
        {
            BeginInit();
            InitDataSet(iFieldID, strDataSetName);
            EndInit();
        }

        public THSDataSet(String strDataSetName,String[] saTableNames)
        {
            BeginInit();
            //Init Data Set
            InitDataSet(strDataSetName, saTableNames);
            EndInit();
        }

        public THSDataSet(DataSet ds)
        {
            BeginInit();
            InitDataSet(ds);
            EndInit();
        }

        private void InitDataSet(String strDataSetName, String[] saTableNames)
        {
            this.DataSetName = strDataSetName;
            InitDataTables(saTableNames);
        }

        private void InitDataSet(DataSet ds)
        {
            this.DataSetName = ds.DataSetName;
            InitDataTables(ds);
            InitRelations(ds);
            
        }

        /// <summary>
        /// Init DataSet by DataSet Name
        /// </summary>
        /// <param name="iTHSDataSetID"></param>
        private void InitDataSet(int iTHSDataSetID)
        {
            STTHSDataSetsController objSTTHSDataSetsController= new STTHSDataSetsController();
            STTHSDataSetsInfo objSTTHSDataSetsInfo = (STTHSDataSetsInfo)objSTTHSDataSetsController.GetObjectByID(iTHSDataSetID);
            if(objSTTHSDataSetsInfo!=null)
            {
                this.DataSetName = objSTTHSDataSetsInfo.STTHSDataSetName;
                InitTables(iTHSDataSetID);
                InitRelations(iTHSDataSetID);
            }
        }

        private void InitDataSet(int iFieldID, String strDataSetName)
        {
            STTHSDataSetsController objSTTHSDataSetsController = new STTHSDataSetsController();
            STTHSDataSetsInfo objSTTHSDataSetsInfo = objSTTHSDataSetsController.GetTHSDataSetByFieldIDAndTHSDataSetName(iFieldID, strDataSetName);
            if (objSTTHSDataSetsInfo != null)
            {
                this.DataSetName = objSTTHSDataSetsInfo.STTHSDataSetName;
                InitTables(objSTTHSDataSetsInfo.STTHSDataSetID);
                InitRelations(objSTTHSDataSetsInfo.STTHSDataSetID);
            }
        }

        /// <summary>
        /// Init Tables of DataSet
        /// </summary>
        /// <param name="iTHSDataSetID">DataSetID</param>
        private void InitTables(int iTHSDataSetID)
        {            
            STTHSDataTablesController objSTTHSDataTablesController = new STTHSDataTablesController();
            //Get all data tables in DataSet
            DataSet dsTHSDataTables = objSTTHSDataTablesController.GetTHSDataTableByTHSDataSetID(iTHSDataSetID);
            if (dsTHSDataTables.Tables.Count > 0)
            {
                foreach (DataRow rowTHSDataTable in dsTHSDataTables.Tables[0].Rows)
                {
                    STTHSDataTablesInfo objSTTHSDataTablesInfo = (STTHSDataTablesInfo)objSTTHSDataTablesController.GetObjectFromDataRow(rowTHSDataTable);
                    DataTable table = InitDataTable(objSTTHSDataTablesInfo.STTHSDataTableName);
                    this.Tables.Add(table);
                }
            }            
        }


        private void InitDataTables(String[] saTableNames)
        {
            foreach (String strTableName in saTableNames)
            {
                DataTable table = InitDataTable(strTableName);
                this.Tables.Add(table);
            }
        }

        private void InitDataTables(DataSet ds)
        {
            try
            {
                foreach (DataTable dt in ds.Tables)
                {
                    DataTable table = InitDataTable(dt);
                    this.Tables.Add(table);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        /// <summary>
        /// Init DataTable by Table Name
        /// </summary>
        /// <param name="strTableName">Table Name</param>
        /// <returns></returns>
        private DataTable InitDataTable(String strTableName)
        {
            DataTable table = new DataTable(strTableName);
            
            // Init Columns
            DataSet dsTableColumns = THSDbUtil.GetTableColumns(strTableName);
            if (dsTableColumns.Tables.Count > 0)
            {
                foreach (DataRow rowTableColumn in dsTableColumns.Tables[0].Rows)
                {
                    DataColumn column = InitTableColumn(rowTableColumn);
                    table.Columns.Add(column);
                }
            }           

            return table;

        }

        private DataTable InitDataTable(DataTable dt)
        {
            try
            {
                DataTable table = new DataTable(dt.TableName);
                foreach (DataColumn dc in dt.Columns)
                {
                    DataColumn column = InitTableColumn(dc);
                    table.Columns.Add(column);
                }
                return table;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return null;
            }
        }


        /// <summary>
        /// Init Column
        /// </summary>
        /// <param name="rowTableColumn"></param>
        /// <returns></returns>
        private DataColumn InitTableColumn(DataRow rowTableColumn)
        {
            
            String strColumnName = rowTableColumn["COLUMN_NAME"].ToString();
            String strColumnDataType = rowTableColumn["DATA_TYPE"].ToString();
            String strColumnIsNullable = rowTableColumn["IS_NULLABLE"].ToString();
            DataColumn column = new DataColumn(strColumnName, GetColumnTypeByDataType(strColumnDataType), null);

            //Set column is allowed null or not null
            if (strColumnIsNullable.Equals("NO"))
                column.AllowDBNull = false;
            else
                column.AllowDBNull = true;

            //if Column is Primary key,set column is Unique
            if (THSDbUtil.IsPrimaryKey(rowTableColumn["TABLE_NAME"].ToString(), strColumnName))
                column.Unique = true;

            //if Column Data Type is string,get max length
            if (column.DataType == typeof(string))
                column.MaxLength = Convert.ToInt32(rowTableColumn["CHARACTER_MAXIMUM_LENGTH"].ToString());

            return column;
        }

        private DataColumn InitTableColumn(DataColumn dc)
        {
            DataColumn column = new DataColumn(dc.ColumnName, dc.DataType);
            column.AllowDBNull = dc.AllowDBNull;
            column.Unique = dc.Unique;
            column.MaxLength = dc.MaxLength;

            return column;
        }


        private void InitTableUniqueConstraint(DataTable table, DataRow rowUniqueConstraint)
        {
            String strUniqueConstraintName = rowUniqueConstraint["CONSTRAINT_NAME"].ToString();
            String strColumnName = rowUniqueConstraint["COLUMN_NAME"].ToString();
            String strTableName = rowUniqueConstraint["TABLE_NAME"].ToString();

            UniqueConstraint uniqueConstraint = new UniqueConstraint(strUniqueConstraintName, table.Columns[strColumnName], true);
            table.Constraints.Add(uniqueConstraint);
        }       


        /// <summary>
        /// Init Relations
        /// </summary>
        /// <param name="iTHSDataSetID">DataSetID</param>
        private void InitRelations(int iTHSDataSetID)
        {            
            STTHSDataSetRelationsController objSTTHSDataSetRelationsController = new STTHSDataSetRelationsController();
            DataSet dsTHSDataSetRelations = objSTTHSDataSetRelationsController.GetTHSDataSetRelationByTHSDataSetID(iTHSDataSetID);
            if (dsTHSDataSetRelations.Tables.Count > 0)
            {
                foreach (DataRow rowRelation in dsTHSDataSetRelations.Tables[0].Rows)
                {
                    STTHSDataSetRelationsInfo objSTTHSDataSetRelationsInfo = (STTHSDataSetRelationsInfo)objSTTHSDataSetRelationsController.GetObjectFromDataRow(rowRelation);
                    DataRelation relation = InitRelation(objSTTHSDataSetRelationsInfo);
                    this.Relations.Add(relation);
                }
            }            
        }


        private void InitRelations(DataSet ds)
        {
            foreach (DataRelation relation in ds.Relations)
            {
                this.Relations.Add(relation);
            }
        }


        private DataRelation InitRelation(STTHSDataSetRelationsInfo objSTTHSDataSetRelationsInfo)
        {            
            String strRelationName = objSTTHSDataSetRelationsInfo.STTHSDataSetRelationName;            
            String strPrimaryTable = objSTTHSDataSetRelationsInfo.STTHSDataSetRelationPrimaryTable;            
            String strPrimaryColumn = objSTTHSDataSetRelationsInfo.STTHSDataSetRelationPrimaryColumn;            
            String strForeignTable = objSTTHSDataSetRelationsInfo.STTHSDataSetRelationForeignTable;            
            String strForeignColumn = objSTTHSDataSetRelationsInfo.STTHSDataSetRelationForeignColumn;

            DataRelation relation = new DataRelation(strRelationName, this.Tables[strPrimaryTable].Columns[strPrimaryColumn], this.Tables[strForeignTable].Columns[strForeignColumn],false);            
            return relation;
        }


        /// <summary>
        /// Get Column Type by Column Data Type
        /// </summary>
        /// <param name="strDataType">Data Type</param>
        /// <returns></returns>
        private Type GetColumnTypeByDataType(String strDataType)
        {
            switch (strDataType)
            {
                case "smallint":
                case "int":
                    {
                        return typeof(int);
                    }
                case "bigint":
                    {
                        return typeof(long);
                    }
                case "varchar":
                case "text":
                case "ntext":
                case "nvarchar":
                    {
                        return typeof(string);
                    }
                case "float":
                    {
                        return typeof(double);
                    }
                case "real":
                    {
                        return typeof(float);
                    }
                case "smalldatetime":
                case "datetime":
                    {
                        return typeof(System.DateTime);
                    }
                case "smallmoney":
                case "money":
                    {
                        return typeof(decimal);
                    }
                case "bit":
                    {
                        return typeof(bool);
                    }

                case "image":
                case "varbinary":
                    {
                        return typeof(byte[]);
                    }
                
            }
            return typeof(string);
        }
    }
}
